package com.zhaolixiang.camera02

import android.app.Activity
import android.content.Context
import android.graphics.ImageFormat
import android.graphics.SurfaceTexture
import android.hardware.camera2.*
import android.media.Image
import android.media.ImageReader
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.os.Handler
import android.os.HandlerThread
import android.view.TextureView
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.util.concurrent.Semaphore
import java.util.concurrent.TimeUnit
import android.widget.Toast
import android.support.annotation.NonNull
import java.util.Arrays.asList
import android.opengl.ETC1.getHeight
import android.opengl.ETC1.getWidth
import android.util.Log
import android.util.Size
import android.util.SparseIntArray
import android.view.Surface
import java.util.*


class MainActivity : AppCompatActivity() {
    private lateinit var activity: Activity;
    //CameraManager：摄像头管理器。这是一个全新的系统管理器，专门用于检测系统摄像头、打开系统摄像头。
    // 另外，调用CameraManager的getCameraCharacteristics(String cameraId)方法即可获取指定摄像头的相关特性。
    private lateinit var cameraManager: CameraManager
    //利用manager获得相机ID
    private var mCameraId: String = ""
    //CameraDevice：代表系统摄像头。该类的功能类似于早期的Camera类。
    // 而每个 CameraDevice 自己会负责建立 CameraCaptureSession 以及建立 CaptureRequest。
    private var mCameraDevice: CameraDevice? = null
    private val ORIENTATIONS = SparseIntArray()
    private inner class ImageSaver(img: Image, f: File) : Runnable {
        //JPEF 图片
        private var image: Image? = null
        //要保持到的文件
        private var file: File? = null

        init {
            image = img
            file = f
        }

        override fun run() {
            val byteBuffer = image!!.planes[0].buffer
            val bytes = ByteArray(byteBuffer.remaining())
            byteBuffer.get(bytes)

            var fileOutputStream: FileOutputStream? = null
            try {
                fileOutputStream = FileOutputStream(file)
                fileOutputStream.write(bytes)
            } catch (e: IOException) {
                e.printStackTrace()
            } finally {
                image!!.close()
                if (null != fileOutputStream) {
                    try {
                        fileOutputStream.close()
                    } catch (e: IOException) {
                        e.printStackTrace()
                    }

                }
            }
        }

    }
    //利用manager获得相机ID列表
    fun getCameraId() {
        //通过标识符返回当前连接的相机设备列表，包括可能由其他相机API客户端使用的相机。
        for (item in cameraManager.cameraIdList) {
            //查询相机设备的功能
            //CameraCharacteristics：摄像头特性。该对象通过CameraManager来获取，用于描述特定摄像头所支持的各种特性。类似与原来的CameraInfo 。
            val cameraCharacteristics = cameraManager.getCameraCharacteristics(item)
            //lens facing--镜头面对
            if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
                continue
            }
            mCameraId = item
            return
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        activity = this
        ORIENTATIONS.append(Surface.ROTATION_0, 90);
        ORIENTATIONS.append(Surface.ROTATION_90, 0);
        ORIENTATIONS.append(Surface.ROTATION_180, 270);
        ORIENTATIONS.append(Surface.ROTATION_270, 180);

        //初始化CameraManager
        cameraManager = activity.getSystemService(Context.CAMERA_SERVICE) as CameraManager
        mFile = File(Environment.getExternalStorageDirectory().getAbsolutePath(), "1.jpg")
        if (!mFile.exists()) {
            mFile.createNewFile()
        }
        bt_get.setOnClickListener {
            //720*1027
            //720*1120
            //720*1230
            Log.e("打开相机的高度和宽：", "w:" + textureView.getWidth() + ";h:" + textureView.getHeight())

            openCamera(textureView.getWidth(), textureView.getHeight());
        }
        captureButton.setOnClickListener {
            lockFocus();
        }
    }

    //打开相机
    fun openCamera(width: Int, height: Int) {
        try {

            //利用manager获得相机ID
            getCameraId()
             // 获取指定摄像头的特性
            val characteristics
                = cameraManager.getCameraCharacteristics(mCameraId);
            // 获取摄像头支持的配置属性
            val map = characteristics.get(
                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            // 获取摄像头支持的最大尺寸


            //拍照时候获取图片用的，预览size确定了，我们可以初始化它了
            //参数1:默认图像的宽度像素
            //参数2:默认图像的高度像素
            //参数3:图像的格式
            //参数4:用户想要读图像的最大数量
            imageReader = ImageReader.newInstance(1080, 1920, ImageFormat.JPEG, 1)
            //注册一个监听器，当新图片可以时
            //参数2：侦听器应该被调用的处理程序，如果在调用线程的线程上调用侦听器，则该处理程序为null。
            imageReader!!.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler)
            if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
                throw RuntimeException("Time out waiting to lock camera opening.")
            }
            //打开相机
            cameraManager.openCamera(mCameraId, mStateCallback, backgroundHandler)
        } catch (e: Exception) {
            Toast.makeText(activity, "相机打开失败", Toast.LENGTH_LONG)
            e.printStackTrace()
        }

    }
     // 为Size定义一个比较器Comparator
   private inner class CompareSizesByArea : Comparator<Size> {
         override fun compare(lhs: Size, rhs: Size): Int {
             // 强转为long保证不会发生溢出
             return java.lang.Long.signum(lhs.getWidth() as Long * lhs.getHeight() - rhs.getWidth() as Long * rhs.getHeight())
         }
     }
    private val mStateCallback = object : CameraDevice.StateCallback() {

        override fun onOpened(cameraDevice: CameraDevice) {
            mCameraOpenCloseLock.release()
            mCameraDevice = cameraDevice
            createCameraPreviewSession()
        }

        override fun onDisconnected(cameraDevice: CameraDevice) {
            mCameraOpenCloseLock.release()
            cameraDevice.close()
            mCameraDevice = null
        }

        override fun onError(cameraDevice: CameraDevice, error: Int) {
            mCameraOpenCloseLock.release()
            cameraDevice.close()
            mCameraDevice = null
        }
    }
    private fun createCameraPreviewSession() {
        try {
            val texture = textureView.getSurfaceTexture()
            // 我们将默认缓冲区的大小配置为我们想要的摄像机预览的大小。
            texture.setDefaultBufferSize(1920, 1080)
            //这是我们需要开始预览的输出面。
            val surface = Surface(texture)
            mPreviewBuilder = mCameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
            mPreviewBuilder!!.addTarget(surface)//预览时，是将Surface()作为目标
            // 设置自动对焦模式
            mPreviewBuilder!!.set(CaptureRequest.CONTROL_AF_MODE,
                CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            // 设置自动曝光模式
            mPreviewBuilder!!.set(CaptureRequest.CONTROL_AE_MODE,
                CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            // 获取设备方向
            val rotation = getWindowManager().getDefaultDisplay().getRotation();
            // 根据设备方向计算设置照片的方向
            mPreviewBuilder!!.set(CaptureRequest.JPEG_ORIENTATION
                , ORIENTATIONS.get(rotation));
            //开始预览
            mState = STATE_PREVIEW
            //创建配置
            mCameraDevice!!.createCaptureSession(
                    Arrays.asList(surface, imageReader!!.getSurface()),
                    object : CameraCaptureSession.StateCallback() {
                        override fun onConfigured(cameraCaptureSession: CameraCaptureSession) {
                            // 摄像机已经关闭了
                            if (null == mCameraDevice) {
                                return
                            }
                            mCaptureSession = cameraCaptureSession
                            try {
                                //配置参数
                                //自动对焦control mode--control  mode -auto
                                mPreviewBuilder!!.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
                                //自动对焦control af mode --control af mode continuous picture
                                //mPreviewBuilder!!.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
                               //自动曝光control af mode --control ad mode on auto flash
                                //mPreviewBuilder!!.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)
                                // 强制曝光control af mode --control ad mode on always flash
                                //mPreviewBuilder!!.set(CaptureRequest.CONTROL_AE_MODE,CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
                                //不闪光control af mode --control ad mode on auto flash redeye
                               // mPreviewBuilder!!.set(CaptureRequest.CONTROL_AE_MODE,CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE);
                                mPreviewRequest = mPreviewBuilder!!.build()
                                mCaptureSession!!.setRepeatingRequest(mPreviewRequest, mCaptureCallback, backgroundHandler)
                            } catch (e: CameraAccessException) {
                                e.printStackTrace()
                                Log.e("linc", "set preview builder failed." + e.message)
                            }

                        }

                        override fun onConfigureFailed(cameraCaptureSession: CameraCaptureSession) {
                            Toast.makeText(activity, "Camera configuration Failed", Toast.LENGTH_SHORT).show()
                        }
                    }, backgroundHandler)
        } catch (e: CameraAccessException) {
            e.printStackTrace()
        }
    }




    //一个后台启动线程
    private var backgroundThread: HandlerThread? = null
    private var backgroundHandler: Handler? = null

    private var imageReader: ImageReader? = null
    private lateinit var mFile: File
    private val mCameraOpenCloseLock = Semaphore(1)

    private var mPreviewBuilder: CaptureRequest.Builder? = null
    private var mPreviewRequest: CaptureRequest? = null
    private var mCaptureSession: CameraCaptureSession? = null
    private val REQUEST_CAMERA_PERMISSION = 1
    private val STATE_PREVIEW = 1;
    private val STATE_WAITING_PRECAPTURE = 2;
    private var mState = STATE_PREVIEW;

    private val mCaptureCallback = object : CameraCaptureSession.CaptureCallback() {
        override fun onCaptureCompleted(session: CameraCaptureSession?, request: CaptureRequest?, result: TotalCaptureResult?) {

            mCaptureSession = session;
            if (result != null) checkState(result);
        }

        override fun onCaptureProgressed(session: CameraCaptureSession?, request: CaptureRequest?, partialResult: CaptureResult?) {
            mCaptureSession = session;
            if (partialResult != null) checkState(partialResult);
        }

        fun checkState(result: CaptureResult) {
            when (mState) {
                STATE_PREVIEW -> {
                    //我们没有什么可做的，当相机预览工作正常的时候。
                }
                STATE_WAITING_PRECAPTURE -> {
                    val afState = result.get(CaptureResult.CONTROL_AF_STATE);
                    if (afState == null) {
                        captureStillPicture();
                    } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState || CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
                        // CONTROL_AE_STATE can be null on some devices
                        val aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                        if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                            //mState = STATE_PICTURE_TAKEN;
                            captureStillPicture();
                        } else {
                            //runPrecaptureSequence();//视频拍摄
                        }
                    }
                }
            }
        }
    }

    private val surfaceTextureListener = object : TextureView.SurfaceTextureListener {
        override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {
            openCamera(width, height);
        }

        override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) {
        }

        override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?): Boolean {
            return true;
        }

        override fun onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) {
        }

    }
    private val onImageAvailableListener = object : ImageReader.OnImageAvailableListener {
        override fun onImageAvailable(reader: ImageReader?) {
            if (backgroundHandler != null && reader != null) {
                backgroundHandler!!.post(ImageSaver(reader.acquireLatestImage(), mFile))
            }
        }
    }


    override fun onResume() {
        super.onResume()
        startBackgroundThread()
        if (textureView.isAvailable) {
            openCamera(textureView.getWidth(), textureView.getHeight());
        } else {
            textureView.surfaceTextureListener = surfaceTextureListener
        }
    }

    override fun onPause() {
        super.onPause()

        stopBackgroundThread()
    }

    fun startBackgroundThread() {
        backgroundThread = HandlerThread("CameraBackgroundThread")
        backgroundThread!!.start()
        backgroundHandler = Handler(backgroundThread!!.looper)
    }

    fun stopBackgroundThread() {
        if (backgroundThread != null) {
            backgroundThread!!.quitSafely()
            backgroundThread!!.join()
            backgroundThread = null
            backgroundHandler = null
        }

    }







    private fun captureStillPicture() {
        try {
            if (null == mCameraDevice) {
                return;
            }
            // This is the CaptureRequest.Builder that we use to take a picture.
            val captureBuilder =
                    mCameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            captureBuilder.addTarget(imageReader!!.getSurface());//拍照时，是将mImageReader.getSurface()作为目标

            // Use the same AE and AF modes as the preview.
            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            captureBuilder.set(CaptureRequest.CONTROL_AE_MODE,
                    CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

            val CaptureCallback = object : CameraCaptureSession.CaptureCallback() {
                public override fun onCaptureCompleted(session: CameraCaptureSession,
                                                       request: CaptureRequest,
                                                       result: TotalCaptureResult) {
                    Log.e("saved--->", mFile.path)
                    //Log.d("customCarmeraActivity", mFile.toString());
                    unlockFocus();//恢复预览
                }
            };

            mCaptureSession!!.stopRepeating();
            mCaptureSession!!.abortCaptures();
            mCaptureSession!!.capture(captureBuilder.build(), CaptureCallback, null);
        } catch (e: CameraAccessException) {
            e.printStackTrace();
        }
    }

    private fun unlockFocus() {
        try {
            // Reset the auto-focus trigger
            mPreviewBuilder!!.set(CaptureRequest.CONTROL_AF_TRIGGER,
                    CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
            mPreviewBuilder!!.set(CaptureRequest.CONTROL_AE_MODE,
                    CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            /*       mCaptureSession.capture(mPreviewBuilder.build(), mCaptureCallback,
                           mBackgroundHandler);*/
            // After this, the camera will go back to the normal state of preview.
            mState = STATE_PREVIEW;
            mCaptureSession!!.setRepeatingRequest(mPreviewBuilder!!.build(), mCaptureCallback, backgroundHandler);
        } catch (e: CameraAccessException) {
            e.printStackTrace();
        }
    }

    /**
     * 将焦点锁定为静态图像捕获的第一步。
     */
    private fun lockFocus() {
        try {
            // This is how to tell the camera to lock focus.
            mPreviewBuilder!!.set(CaptureRequest.CONTROL_AF_TRIGGER,
                    CameraMetadata.CONTROL_AF_TRIGGER_START);
            // Tell #mCaptureCallback to wait for the lock.
            mState = STATE_WAITING_PRECAPTURE;
            mCaptureSession!!.capture(mPreviewBuilder!!.build(), mCaptureCallback,
                    backgroundHandler);
        } catch (e: CameraAccessException) {
            e.printStackTrace();
        }
    }


}
